/**
 * @file time_utils.h
 * @brief 时间处理工具函数
 * @author 电网104协议开发团队
 * @date 2024
 */

#ifndef TIME_UTILS_H
#define TIME_UTILS_H

#include "../include/protocol_types.h"
#include "../include/error_codes.h"
#include "../include/constants.h"
#include <time.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== CP56Time2a解析和构建函数 ==================== */

/**
 * @brief 解析CP56Time2a时间戳
 * @details 从字节流中解析CP56Time2a时间戳，按照协议规范解析各个字段
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param offset 偏移量
 * @param cp56time CP56Time2a结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note CP56Time2a格式：7字节，包含毫秒、分钟、小时、日、月、年、星期
 * @warning 解析后的时间戳需要验证有效性
 * 
 * @see cp56time2a_t
 * @see validate_cp56time2a
 */
protocol_error_t parse_cp56time2a(const uint8_t* buffer, size_t buffer_size, size_t offset, cp56time2a_t* cp56time);

/**
 * @brief 构建CP56Time2a时间戳
 * @details 将CP56Time2a结构转换为字节流，按照协议规范构建各个字段
 * 
 * @param cp56time CP56Time2a结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param offset 偏移量
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 构建成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 * 
 * @note 构建前建议先验证CP56Time2a结构的有效性
 * @warning 输出缓冲区必须有足够的空间(至少7字节)
 * 
 * @see cp56time2a_t
 * @see validate_cp56time2a
 */
protocol_error_t build_cp56time2a(const cp56time2a_t* cp56time, uint8_t* buffer, size_t offset);

/* ==================== 时间转换函数 ==================== */

/**
 * @brief 将系统时间转换为CP56Time2a格式
 * @param system_time 系统时间戳(秒)
 * @param cp56time CP56Time2a时间结构输出
 * @return 协议错误码
 */
protocol_error_t system_time_to_cp56time2a(time_t system_time, cp56time2a_t* cp56time);

/**
 * @brief 将CP56Time2a格式转换为系统时间
 * @param cp56time CP56Time2a时间结构
 * @param system_time 系统时间戳输出(秒)
 * @return 协议错误码
 */
protocol_error_t cp56time2a_to_system_time(const cp56time2a_t* cp56time, time_t* system_time);

/**
 * @brief 获取当前时间的CP56Time2a格式
 * @param cp56time CP56Time2a时间结构输出
 * @return 协议错误码
 */
protocol_error_t get_current_cp56time2a(cp56time2a_t* cp56time);

/**
 * @brief 验证CP56Time2a时间是否有效
 * @param cp56time CP56Time2a时间结构
 * @return 有效返回true，无效返回false
 */
int is_cp56time2a_valid(const cp56time2a_t* cp56time);

/**
 * @brief 比较两个CP56Time2a时间
 * @param time1 时间1
 * @param time2 时间2
 * @return 时间1早于时间2返回-1，相等返回0，晚于返回1
 */
int compare_cp56time2a(const cp56time2a_t* time1, const cp56time2a_t* time2);

/**
 * @brief 计算两个CP56Time2a时间的差值(毫秒)
 * @param time1 时间1
 * @param time2 时间2
 * @param diff_ms 时间差输出(毫秒)
 * @return 协议错误码
 */
protocol_error_t cp56time2a_diff_ms(const cp56time2a_t* time1, const cp56time2a_t* time2, int32_t* diff_ms);

/**
 * @brief CP56Time2a时间增加毫秒数
 * @param cp56time CP56Time2a时间结构(输入输出)
 * @param ms 要增加的毫秒数
 * @return 协议错误码
 */
protocol_error_t cp56time2a_add_ms(cp56time2a_t* cp56time, int32_t ms);

/**
 * @brief 将CP56Time2a时间转换为字符串
 * @param cp56time CP56Time2a时间结构
 * @param buffer 输出缓冲区
 * @param buffer_size 缓冲区大小
 * @param format 时间格式字符串
 * @return 协议错误码
 */
protocol_error_t cp56time2a_to_string(const cp56time2a_t* cp56time, char* buffer, size_t buffer_size, const char* format);

/**
 * @brief 将字符串转换为CP56Time2a时间
 * @param time_str 时间字符串
 * @param format 时间格式字符串
 * @param cp56time CP56Time2a时间结构输出
 * @return 协议错误码
 */
protocol_error_t string_to_cp56time2a(const char* time_str, const char* format, cp56time2a_t* cp56time);

/* ==================== 时间格式化函数 ==================== */

/**
 * @brief 获取默认时间格式字符串
 * @return 默认时间格式字符串
 */
const char* get_default_time_format(void);

/**
 * @brief 获取ISO 8601时间格式字符串
 * @return ISO 8601时间格式字符串
 */
const char* get_iso8601_time_format(void);

/**
 * @brief 获取紧凑时间格式字符串
 * @return 紧凑时间格式字符串
 */
const char* get_compact_time_format(void);

/* ==================== 时间验证函数 ==================== */

/**
 * @brief 验证年份是否在有效范围内
 * @param year 年份
 * @return 有效返回true，无效返回false
 */
int is_year_valid(uint8_t year);

/**
 * @brief 验证月份是否有效
 * @param month 月份
 * @return 有效返回true，无效返回false
 */
int is_month_valid(uint8_t month);

/**
 * @brief 验证日期是否有效
 * @param year 年份(相对于1992年)
 * @param month 月份
 * @param day 日期
 * @return 有效返回true，无效返回false
 */
int is_day_valid(uint8_t year, uint8_t month, uint8_t day);

/**
 * @brief 验证小时是否有效
 * @param hour 小时
 * @return 有效返回true，无效返回false
 */
int is_hour_valid(uint8_t hour);

/**
 * @brief 验证分钟是否有效
 * @param minute 分钟
 * @return 有效返回true，无效返回false
 */
int is_minute_valid(uint8_t minute);

/**
 * @brief 验证秒是否有效
 * @param second 秒
 * @return 有效返回true，无效返回false
 */
int is_second_valid(uint8_t second);

/**
 * @brief 验证毫秒是否有效
 * @param millisecond 毫秒
 * @return 有效返回true，无效返回false
 */
int is_millisecond_valid(uint16_t millisecond);

#ifdef __cplusplus
}
#endif

#endif /* TIME_UTILS_H */
